var loadingText = "loading...";
var debug = false;
var floatTooltip = false;

var gMouseMoveEv =  null;

var gHostName = window.location.hostname;
var gHostPort = window.location.port;

//TODO: capture the focus of the document - if we lose focus while mouse is down, release mouse, and regain focus
// there is a bug where the placholder is stuck as an element in the UI. In this way one can create multiple placeholders
//add an element
//the element to add to, element to add, number of times to add
function addHtml (element, htmlString, repeat){
	//TODO: add the inline html, use this to add other elements - tasting notes, varietal
	element.innerHTML = oxUtil.unquote(htmlString);
}

//drag and drop functions
document.onmousemove = mouseMove;
document.onmouseup = mouseUp;
var dropTargets = [];
var dropTarget = null;

var dragTargets = [];
var dragObject     = null;
var dragObjectStartWidth = null;
var dragObjectStartHeight = null;
var dragObjectMargin = 0;

var dragObjectOrigDisplay = null;
var placeholderOrigDisplay = null;;

var	sDropTargets = [];
var	sDragTargets = [];

var placeholder = null;


function makeDraggable(item){
	if(!item) return;
	item.onmousedown = function(ev){
		if (ev.target.className == ("widgetHeader") || ev.target.className== ("widgetHeaderInput") )
		{
			placeholder = null;
			dragObject  = this;
			dragObject.setAttribute("style","z-index:50;");
			dragParent = this.parentNode;
			dragStartY = this.style.top;
			dragObjectOrigDisplay = this.style.display;

			mouseOffset = getMouseOffset(this, ev);

			dragObjectStartWidth = this.offsetWidth - 0; //must subtract 2 * the border width in Firefox: cannot access border-width programmatically
			dragObjectStartHeight = this.offsetHeight;

			createPlaceHolder(dragObject);		//add the outlined placeholder
			this.style.display = "none";
			setStaticTargets();
			this.style.display = dragObjectOrigDisplay;
			return false;
		}
		return true;
	}
	dragTargets.push(item);
	return false;
}


function makeDroppable(item) {
	dropTargets.push(item);
	return false;
}


function createPlaceHolder(dragObject) {
	placeholder = document.createElement("div");
	placeholder.setAttribute("id","placeholder");
	placeholder.style.position = 'absolute';
	var phWidth = 3;
	//this margin must equal the widget margin
	placeholder.setAttribute("style","margin:4px;border-color:1daf2f;border-width:"+ phWidth +"px;border-style:dashed;z-index:1;");
	placeholder.style.height = dragObjectStartHeight - (2 * phWidth);
	placeholder.style.width = null;// sizes it according to the container needs...			
	//alert("ph w:" + placeholder.style.width + "  h:" + placeholder.style.height);
	placeholderOrigDisplay = placeholder.style.display;
	placeholder.style.display="none";
	dragObject.parentNode.insertBefore(placeholder, dragObject);
}


function setDragObject(ev) {
	var mouseLoc = mouseLocation(ev);
	dragObject.style.position = 'absolute';
	dragObject.style.display = dragObjectOrigDisplay;
	//TODO: if this is the top item, subtract margin from its location
	dragObject.style.top      = mouseLoc.y - mouseOffset.y - 4; //the margin must be subtracted for both x and y
	dragObject.style.left     = mouseLoc.x - mouseOffset.x - 4; //in order to avoid the 'jump' when selecting for drag
	dragObject.style.width   = dragObjectStartWidth;
	//alert("start width:" + dragObjectStartWidth);
}


//handles the document level mousemove event
function mouseMove(ev) {
	ev           = ev || window.event;
	gMouseMoveEv = ev;

	if (floatTooltip)
	{
		var mouseLoc = mouseLocation(ev);
		//document.getElementById("rsstooltip").setAttribute("style","position:absolute;width:400;left:"+
		//												  (mouseLoc.x + 20)+";top:"+ (mouseLoc.y + 20)+";");
		document.getElementById("rsstooltip").style.left =  mouseLoc.x + 20;
		document.getElementById("rsstooltip").style.top =   mouseLoc.y + 20;
	}

	if(dragObject) {
		var mouseLoc = mouseLocation(ev);

		if (!placeholder) { createPlaceHolder(dragObject); }
		placeholder.style.display = placeholderOrigDisplay;
		setDragObject(ev);

		for(var i=0; i<sDropTargets.length; i++) {
			var realDropTarget  =	dropTargets[i];
			var sDropTarget  =		sDropTargets[i];
			var sDropPos    = getPosition(sDropTarget);
			var sDropWidth  = parseInt(sDropTarget.offsetWidth);
			var sDropHeight = parseInt(sDropTarget.offsetHeight);

			if( (mouseLoc.x > sDropPos.x)                &&
				(mouseLoc.x < (sDropPos.x + sDropWidth)) )
			{
				//the cursor is dragging an object
				//and is between two column sides but
				//no necessarily within the top and bottom boundaries
				//so set the column
				if ( (mouseLoc.y > sDropPos.y)                &&
					 (mouseLoc.y < (sDropPos.y + sDropHeight)) )
				{
					
					//dragObject is within the boundaries of a dropTarget
					//check to see which draggableTarget it is above
					//and then insert the placeholder above that draggableTarget
					var dt = false; //used to place the widget in case there are is just an empty column
					for(var j=0; j<sDragTargets.length; j++){
						var realDragTarget  = dragTargets[j];
						var sDragTarget  = sDragTargets[j];
						var sDragPos    = getPosition(sDragTarget);
						var sDragWidth  = parseInt(sDragTarget.offsetWidth);
						var sDragHeight = parseInt(sDragTarget.offsetHeight);
						
						if (
							(mouseLoc.x > sDragPos.x)                &&
							(mouseLoc.x < (sDragPos.x + sDragWidth))  &&
							(mouseLoc.y > sDragPos.y - (dragObjectMargin/2) )                &&
							(mouseLoc.y < (sDragPos.y + sDragHeight + ((dragObjectMargin/2) + 1)   )) )
						{
							placeholder.parentNode.removeChild(placeholder);
							realDragTarget.parentNode.insertBefore(placeholder, realDragTarget);

							//found the target, end the loop
							j = sDragTarget.length;
							i = sDropTarget.length;
							dt = true;
							//alert("dt true");
						}
					} // end dragTarget for loop

					//it is within the X and Y boundaries but there is no target
					//and we have looped through all elements
					if ( (!dt)  // took this extra check out - was causing last widget added to fail in this check adn seems to work anyway
						 )		//&& (mouseLoc.x > sDropPos.x) && (mouseLoc.x < (sDropPos.x + sDragWidth)) 
					{
						//alert("hit it");
						placeholder.parentNode.removeChild(placeholder);
						realDropTarget.appendChild(placeholder);
					}

				} //end dropY if
				else {
					if (mouseLoc.y > (sDropPos.y + sDropHeight) )
					{
						//it is below the lowest boundary
						//put placeholder at bottom
						placeholder.parentNode.removeChild(placeholder);
						realDropTarget.appendChild(placeholder);
					}
					if (mouseLoc.y < sDropPos.y )
					{
						// it as above the highest boundary
						// put placeholder at top
						placeholder.parentNode.removeChild(placeholder);
						realDropTarget.insertBefore(placeholder, realDropTarget.firstChild);
					}
				} //end dropY if.. else
			} // end dropX if
				
		} // end dropTarget for loop
	} //end dragObject if
		return false;
} //end function


//creates a coordinate map of the drop and drag targets
//the map is created with all objects in their orginal position
//must be called after the dragObject is set
function setStaticTargets() {
	for (var i=0;i<dropTargets.length;i++)
	{
		//alert("dropTarget" + i + "  " + dropTargets[i]);
		sDropTargets[i] = {offsetWidth:dropTargets[i].offsetWidth,
						   offsetHeight:dropTargets[i].offsetHeight,
						   offsetParent:dropTargets[i].offsetParent,
						   offsetLeft:dropTargets[i].offsetLeft,
						   offsetTop:dropTargets[i].offsetTop
		}
	}
	for (var i=0;i<dragTargets.length;i++)
	{
		sDragTargets[i] ={ offsetWidth:dragTargets[i].offsetWidth,
						   offsetHeight:dragTargets[i].offsetHeight,
						   offsetParent:dragTargets[i].offsetParent,
						   offsetLeft:dragTargets[i].offsetLeft,
						   offsetTop:dragTargets[i].offsetTop
		}
	}
}


//handles the document level onmouseup event
function mouseUp(ev){

	//originally checked for DO and PH. Rare cases where both do not exist but one does
	// so only check for DO now.
	if ((dragObject != null) )
	{		
		
		//get rid of the drag objects location and size style
		//this allows the browser ot fit it perfectly in the column
		dragObject.style.top      = 0;
		dragObject.style.left     = 0;
		placeholder.parentNode.insertBefore(dragObject, placeholder);
		//TODO: if the dragObject has lost it's parent node, put it at the top of column 1

		dragObject.style.position = 'relative';
		dragObject.setAttribute("style","z-index:1;");
		dragObject.style.width = null;
		dragObject.style.height = null;

		//reset all of the variable
		dropTarget = null;	
		dragObject = null;
		dragObjectStartWidth = null;
		placeholder.parentNode.removeChild(placeholder);
		placeholder = null;
	}
}

function mouseLocation(e){
	//again, handles the firefox vs. MS case
	if(e.pageX || e.pageY){
		//relative to the page
		return {x:e.pageX, y:e.pageY};
	}
	return {
		//relative to the window (center of 500x500 screen will always be 250x250)
		x:e.clientX + document.body.scrollLeft - document.body.clientLeft,
		y:e.clientY + document.body.scrollTop  - document.body.clientTop
	};
}


function getMouseOffset(target, ev){
	debug = false;
	ev = ev || window.event;

	//docPos finds the current location of the current object
	var docPos    = getPosition(target);
	//mousePos is the location of the mouse
	var mousePos  = mouseLocation(ev);
	if (debug)
	{
		alert("mouse offsetX:" + (mousePos.x - docPos.x) + " offsetY:" + (mousePos.y - docPos.y) )
	}
	return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}


//gets the position of an element
function getPosition(e){
	var left = 0;
	var top  = 0;

	while (e.offsetParent){
		left += e.offsetLeft;
		top  += e.offsetTop;
		e     = e.offsetParent;
	}

	left += e.offsetLeft;
	top  += e.offsetTop;

	return {x:left, y:top};
}


function updateAttribute(root, id, node, att, val) {
	debug = false;
	
	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/updateAttribute.xqy?root='+root+'&id='+id+'&node='+node+'&att='+att+'&val='+val;

	if (debug)
	{
		alert("updateAttribute: " + url);
	}

	//the callback in this case is used only to log an error
	//once the request is made, that is all we need
	function callbackBind(){
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (debug)
				{
					alert("response: " + req.responseText);
				}
			} else {
				//TODO: This should log the problem
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null;

	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);

}

//updates the text node of a given element
//updates the date modified attribute of the element node containing the text
//updates the date modified attribute of the root element node
//if the element does not exist, it will create the node
//with dateCreated attribute set (in xquery call), dateModified attribute set, and value set
function updateElementText(root, id, node, val) {
	debug = false;
	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/updateElementText.xqy?root='+root+'&id='+id+'&node='+node+'&value='+val;
	if (debug)
	{
		alert("updateElementText: " + url);
	}
	function callbackBind(){
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (debug)
				{
					alert("response: " + req.responseText);
				}
				updateAttribute(root, id,   "", "dateModified" , "currentdatetime");
				updateAttribute(root, id, node, "dateModified" , "currentdatetime");
			} else {
				//TODO: This should log the problem
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null;

	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);
}

//root: an xquery root e.g. doc('wine.xml')/wines
//element: a complete node element e.g. <name class='wine'>rombauer</name>
//		   when the root is passed the ' typically need to be escaped with a \
//		   this in turn may require the \ to be escaped creating a pattern like this var root = "doc(\\\'wine.xml\\\')"
function insertElement(root, element, cb) {
	debug = false;

	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					cb(req.responseText);
				} else {
					//alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null;


	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/insertElement.xqy?root='+root+'&element='+element;
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);
}


function deleteElement(root, element, cb) {
	debug = false;

	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					cb(req.responseText);
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null;

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/deleteElement.xqy?root='+root+'&element='+element;
	if (debug) {alert("deleteElement: " + url);}
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);
}






///not currently used
function existsElement(root, element) {
	debug = false;
	//element = escape(element);
	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/existsElement.xqy?root='+root+'&element='+element;
	if (debug) {alert("existsElement: " + url);}
	req = new XMLHttpRequest();
	req.open('GET', url, true);
	req.send(null);
	if (req.readyState == 4) {
		if (req.status == 200) {
			if (debug) {alert("response:\n" + req.responseText);}
			return true;
		} else {
			//TODO: This should log the problem
			alert("There was a problem checking if an xml element exists:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
		}
	} 
	//updateAttribute(root, id, "", "dateModified" , "currentdatetime")
	//TODO: need to add the modifier attribute to the inserted elements so that they have created and modified attributes
}

function existsValueSingle(element,value) {
	debug = false;
	//element = escape(element);
	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/existsValue.xqy?element='+element+'&value='+value;
	if (debug) {alert("existsValue url: " + url);}
	req = new XMLHttpRequest();
	req.open('GET', url, false);
	req.send(null);
	if (debug) {alert("existsValue response: " + req.responseText);}
	return req.responseText;

}


//thread safe by using a callback to set the value
function getValuesJSON(root, id, node, callback) {
	var debug = false;
	if (debug)
	{ alert("getValuesJSON called"); }

	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					cb(req.responseText);
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null;
	var cb=callback;

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/getValuesJSON.xqy?root='+root+'&id='+id+'&node='+node;
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);
}

//thread safe by using a callback to set the value
function countElement(root, id, node, callback) {
	var debug = false;
	if (debug)
	{ alert("countElement called"); }

	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					cb(req.responseText);
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null;
	var cb=callback;

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/countElement.xqy?root='+root+'&id='+id+'&node='+node;
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);
}


//thread safe (client side pov) access to data store
//rewuires a callback function that will be called when the data has returned for the request
function getValue(root, id, node, callback) {
	var debug = false;
	
	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					cb(req.responseText);
					if (debug)
					{ alert("getValue response: " + req.responseText)}
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null
	var cb = callback;

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/getValue.xqy?root='+root+'&id='+id+'&node='+node;
	if (debug)
	{alert("getValue URL: "+url)
	}
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);

	
	return loadingText;
}

//thread safe (client side pov) access to data store
//rewuires a callback function that will be called when the data has returned for the request
function getOnHand(root, id, node, callback) {
	var debug = false;
	
	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					var onhand = 0;
					var oh = req.responseText.split("\n");
					for (var i=0; i < oh.length; i++) {
						onhand = onhand + parseInt(oh[i]);
					}
					//alert(oh.length + "oh: " + oh);
					cb(onhand);
					if (debug)
					{ alert("getonHand response: " + onhand +"og:" + req.responseText)}
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null
	var cb = callback;

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/getValue.xqy?root='+root+'&id='+id+'&node='+node;
	if (debug)
	{alert("getValue URL: "+url)
	}
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);

	
	return loadingText;
}


function executeQuery(q, callback) {
	var debug = false;
	
	function callbackBind(){
		//alert("bound callback for " + url + "\n" + req.readyState); 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					cb(req.responseText);
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null
	var cb = callback;

	var url='http://localhost:8002/'+q;
	req = new XMLHttpRequest();
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	req.send(null);

	return loadingText;
}



function executeQuerySingle(q) {
	var debug = false;

	var req = null
	var url='http://localhost:8002'+q;
	req = new XMLHttpRequest();
	req.open('GET', url, false);
	req.send(null);
	return req.responseText;
}



function httpRequestServer(q, callback) {
	var debug = false;
	if (debug) { alert("httpRequest: " + q);} 
	
	function callbackBind(){
		var debug = false;
		if (debug) { alert("bound callback for " + url + "\n" + req.readyState); } 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					if (debug) {alert(req.responseText);}
					cb(req.responseText);
				} else {
					alert('no callback defined');
				}
			} else {
				alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null
	var cb = callback;

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/httpRequestServer.xqy?url=' + q;
	req = new XMLHttpRequest();
	if (debug) { alert("httpRequest: XMLHttpRequest created");} 
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	if (debug) { alert("httpRequest: req.open called");}
	req.send(null);

	return loadingText;

}

//same as httpRequestServer but single threaded
//this is used so that functions that need a response
//before continuing will not have to create wait loops
//whcih appear to really slow down the javascript VM
// e.g. from 200 ms to 
function httpRequestServerSingle(q) {
	var debug = false;
	if (debug) { alert("httpRequest: " + q);} 

	var url='http://'+gHostName+':'+gHostPort+'/porvino/lib/ox/httpRequestServer.xqy?url=' + q;
	req = new XMLHttpRequest();
	if (debug) { alert("httpRequest: XMLHttpRequest created");} 

	req.open('GET', url, false);
	if (debug) { alert("httpRequest: req.open called");}
	req.send(null);

	return req.responseText;
}


function httpRequest(q, callback) {
	var debug=false;
	if (debug) { alert("httpRequest: " + q);} 
	
	function callbackBind(){
		var debug = false;
		if (debug) { alert("bound callback for " + url + "\n" + req.readyState); } 
		if (req.readyState == 4) {
			if (req.status == 200) {
				if (cb){
					if (debug) {alert(req.responseText);}
					cb(req.responseText);
				} else {
					//alert('no callback defined');
				}
			} else {
				if (debug) alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText);
			}
		}
	}
	var req = null
	var cb = callback;

	var url=q;
	req = new XMLHttpRequest();
	if (debug) { alert("httpRequest: XMLHttpRequest created");} 
	req.onreadystatechange = callbackBind;
	req.open('GET', url, true);
	if (debug) { alert("httpRequest: req.open called");}
	req.send(null);

	
	return "";
}


function loadTab(caller, link) {
	var debug = false;
	if (debug) { alert("loadTab: " + caller.id); }
	
	//update the tabs
	tabs = document.getElementById("tabrow").childNodes;
	for (var i=0; i<tabs.length; i++) {
		//alert("type: " + tabs[i].nodeType + "\n" +
		//	  "value: " + tabs[i].nodeValue);
		if (tabs[i].nodeType == Node.ELEMENT_NODE)
		{
			var att = tabs[i].getAttribute("class");
			if ((att == "tab") || (att == "tab_selected"))
			{
				tabs[i].setAttribute("class","tab");
				tabs[i].selected = "false";
			}
		}
	}
	caller.setAttribute("class","tab_selected");
	caller.selected = "true";
	
	//update the body of the application
	var body = document.getElementById("body");
	//body.innerHTML = httpRequestServerSingle("http://localhost:8002" + link);
	body.innerHTML = executeQuerySingle(link);


	//get the widgets and make draggable and load
	var widgets = document.getElementsByTagName("div");
	for (var i=0; i<widgets.length; i++)
	{
		//Initialize well known widgets
		if (widgets[i].getAttribute("type") == "rss") {
			loadRssContent(widgets[i]);
			makeDraggable(document.getElementById(widgets[i].id));
		} else if (widgets[i].getAttribute("type") == "GSearchWidget") {
			try{
				GSearch.setOnLoadCallback(GSearchInit(document.getElementById("searchcontrol")));
			} catch(e) {}
			makeDraggable(document.getElementById(widgets[i].id));
		} else if (widgets[i].getAttribute("type") == "list") {
			//initialize the widget
			makeDraggable(document.getElementById(widgets[i].id));
		} else if (widgets[i].getAttribute("type") == "widget") {
			//alert("found widget: " + widgets[i] + "\n" +
			//	  "wid: " + widgets[i].getAttribute("wid"));
			//need to handle a generic widget
			var scr = document.getElementById("widgetscript"+widgets[i].getAttribute("wid")).firstChild.nodeValue;
			//alert(scr);
			eval(scr);
			makeDraggable(document.getElementById(widgets[i].id));
		}
	}

	//get the drop zones and make droppable
	var containerNode = document.getElementById("widgettable").firstChild.firstChild;
	var cols = containerNode.childNodes;
	for (var i=0;i<cols.length; i++)
	{
		if ((cols[i].nodeType == Node.ELEMENT_NODE) && (cols[i].getAttribute("type") == "dropTarget"))
		{	
			makeDroppable(document.getElementById(cols[i].id));
		}
	}
}